package com.ys.web.pay.conrtoller;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import com.ys.base.BaseConstants;
import com.ys.base.EnumType;
import com.ys.utils.annotation.RiskValidation;
import com.ys.utils.annotation.UserGroupNumberCheck;
import com.ys.utils.annotation.UserWithdrawBlack;
import com.ys.utils.base.http.McodeHandler;
import com.ys.utils.base.http.ResponseHandler;
import com.ys.utils.base.j2se.*;
import com.ys.utils.help.GroupUtils;
import com.ys.utils.help.UserUtils;
import com.ys.utils.http.RSAUtils;
import com.ys.utils.pay.Result;
import com.ys.utils.redis.Redis;
import com.ys.utils.redis.key.GroupKey;
import com.ys.utils.redis.key.WalletKey;
import com.ys.utils.spring.config.SystemError;
import com.ys.utils.spring.properties.Config;
import com.ys.web.pay.PayEnum;
import com.ys.web.pay.RedisKeyToYs;
import com.ys.web.pay.manager.PayManager;
import com.ys.web.pay.model.RedRecordCash;
import com.ys.web.pay.model.po.RedPacketCreate;
import com.ys.web.pay.model.po.RedPacketGrad;
import com.ys.web.pay.service.RedPacketService;
import com.ys.web.user.friends.manager.FriendsManager;
import com.ys.web.user.friends.mapper.UserFriendsMapper;
import com.ys.web.user.friends.po.BaseGroupInfoPO;
import com.ys.web.user.login.LoginInfo;
import com.ys.web.user.login.LoginService;
import com.ys.web.ws.bean.MessageResponseBean;
import com.ys.web.yinsheng.manager.YsWalletManager;
import com.ys.web.yinsheng.model.UserMerchant;
import com.ys.web.yinsheng.service.YinShengService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ 名称:红包相关接口
 * @ 创建人: dhf
 * @ 参数： null
 * @ 创建时间: 2022/5/10
 * @ 修改人和其它信息
 * @ 返回值:
 */
@Slf4j
@RestController
@RequestMapping("/webox/redpacket/")
public class RedPacketController {

    @Autowired
    private UserFriendsMapper userFriendsMapper;
    @Autowired
    private LoginService loginService;
    @Autowired
    private RedPacketService redPacketService;
    @Autowired
    private YinShengService yinShengService;


    @RequestMapping("index")
    public String index() {
        return ResponseHandler.list(Arrays.asList(Config.pp.get("pay.recharge.index.money").split(",")));
    }

    /**
     * 钱包发红包
     *
     * @param uid
     * @param create
     * @return
     */
    @UserWithdrawBlack
    @RiskValidation
    @RequestMapping("create")
    public String createByWallet(@RequestAttribute Long uid,@RequestAttribute String ip, RedPacketCreate create) {
        if (Boolean.parseBoolean(Config.pp.get("trading.disable"))) {
            SystemError.wrapBs("500", "系统维护,交易系统已关闭");
        }
        if (!Boolean.parseBoolean(Config.pp.get("trading.disable.red"))) {
            SystemError.wrapBs("500", "红包已关闭");
        }
        if(create.payChannel<3) {
            if(Logger.isOnline()) {
                if (Boolean.parseBoolean(Config.pp.get("trading.disable.ys"))) {
                    SystemError.wrapBs("500", "银行卡发红包已关闭");
                }
            }
            UserMerchant userMerchant = yinShengService.userMerchant(uid+"");
            //查询发红包人钱包信息 uid
            if(StringHandler.isEmpty(userMerchant)){
                SystemError.wrapBs("601", "该用户还未进行银行卡实名认证");
            }
        }
        if(create.payChannel==3){
            if(Logger.isOnline()) {
                if (!Boolean.parseBoolean(Config.pp.get("trading.disable.red.zfb"))) {
                    SystemError.wrapBs("500", "支付宝发红包已关闭");
                }
            }
        }
        if(create.payChannel==5){
            if(Logger.isOnline()) {
                if (!Boolean.parseBoolean(Config.pp.get("trading.disable.red.hjzf"))) {
                    SystemError.wrapBs("500", "银行卡发红包已关闭");
                }
            }
        }
//        UserUtils.validateUserAccountStatus(StringHandler.getString(uid));
        //验证用户是否能发送红包
        if (create.getGp().equals("2")) {
            //群聊
            BaseGroupInfoPO baseGroupInfoPO = GroupUtils.getCacheGroupInfo(create.getReceivedId());
            if (baseGroupInfoPO.getIsFreeze()) {
                SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "当前群已被禁止使用");
            }

            String key = GroupKey.groupMembersKey(create.getReceivedId());
            Set<String> members = Redis.zSet.range(key, 0, -1);
            if (members == null || members.isEmpty()) {
                SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "当前群已解散");
            } else {
                if (!members.contains(String.valueOf(uid))) {
                    SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "您已不在该群");
                }
            }
        } else {
            //私聊
            int count = userFriendsMapper.isFriend(uid, String.valueOf(McodeHandler.from32Radix(create.getReceivedId())));
            if (count != 2) {
                SystemError.wrapBs("500", "开启了朋友验证，你还不是他(她)朋友，请先发送朋友验证请求，对方验证通过后，才能聊天。");
            }
            LoginInfo receivedId = loginService.infoByUid(StringHandler.getString(McodeHandler.from32Radix(create.getReceivedId())));
            if(receivedId.accountStatus!=0){
                SystemError.wrapBs("500", "好友信息不存在...");
            }
            //排除群聊的情况如果被拉入黑名单
            if (FriendsManager.isBlackFriend(
                    String.valueOf(
                            McodeHandler.from32Radix(
                                    StringHandler.isNotEmpty(create.getReceivedIds()) ? create.getReceivedIds() : create.getReceivedId()))
                    , uid) == 1) {
                SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "你已被对方拉黑");
            }
        }
        // 数据验证
        create.check();

        LoginInfo userVo = loginService.infoByUid(StringHandler.getString(uid));

        if (create.getPayType() == 3 && !PayManager.validatePayPassword(RSAUtils.decryptField(create.getPayPassword()), userVo)) {
            SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), "密码错误");
        }
        //银盛发包金额限制
        if(create.getPayChannel()<3){
            YsWalletManager.checkUserLevel(Convert.objToStr(uid),Convert.objToStr(create.getAmount()), userVo.getRealIdCardUp(), yinShengService.getUserBankCount(uid));
        }
        if (create.getPayType() == 4) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException ignored) {
            }
        }
        // 发红包 加锁
        Result<Map<String, String>> returnResult = redPacketService.giveRedPackage(StringHandler.getString(create.getPacketType()),
                PayEnum.RedPackageType.GroupLuck.getCode().equals(StringHandler.getString(create.getPacketType())) ? create.getAmount() : create.getSingleAmount(),
                StringHandler.getString(create.getPacketCount()), StringHandler.getString(create.getPayType()),
                create.getGp().equals("1") ? create.getReceivedId() : create.getReceivedIds(),
                StringHandler.getString(uid), create.getRemark(), create.getReceivedId(),create.payChannel);
        if (returnResult.success()) {
            // 发送红包推送
            if (create.getPacketType() == 4) {
                create.setReceivedIds(McodeHandler.to32Radix(StringHandler.getLong(create.getReceivedIds())));
            }
            PayManager.send(uid, create, returnResult.getResult().get("redId"), returnResult.getResult().get("messageId"));
        } else {
            SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), returnResult.getMessage());
        }
        return ResponseHandler.success();
    }

    @RequestMapping("isOver")
    public String isOver(@RequestAttribute Long uid, RedPacketGrad grad) {
        RedRecordCash redRecord = redPacketService.getRedRecordCashById(Long.parseLong(grad.getSerialNumber()));
        if(StringHandler.isEmpty(redRecord)){
            SystemError.wrapBs("500", "红包已过期");
        }
        if (redRecord.getRedStatus() == StringHandler.getInt(PayEnum.RedPackageStatus.Processing.getCode())) {
            if (StringHandler.isNotEmpty(grad.getGroupId()) && grad.getRiskNum() > 0 && grad.getRiskTime() > 0) {
                String riskKey = WalletKey.gradUserNumKey(grad.getGroupId(), uid, grad.getRiskTime());
                String oldValue = Redis.str.get(riskKey);
                if (StringHandler.getLong(oldValue) >= grad.getRiskNum()) {
                    SystemError.wrapBs("500", "已达红包领取次数上限");
                }
            }
        }
        return ResponseHandler.success(redRecord.getRedStatus());
    }

    /**
     * 抢红包
     *
     * @param grad
     * @return
     */
    @UserGroupNumberCheck
    @RiskValidation
    @RequestMapping("grad")
    public String getRedPackage(@RequestAttribute long uid,@RequestAttribute String ip, RedPacketGrad grad) {
        if (Boolean.parseBoolean(Config.pp.get("trading.disable"))) {
            return ResponseHandler.error("500", "交易系统已关闭");
        }
        UserUtils.validateUserAccountStatus(StringHandler.getString(uid));
        Result<Map<String, String>> returnResult;

        Object object = Redis.str.get(RedisKeyToYs.REDIS_RED_PREFIX + grad.getSerialNumber());
        if (StringHandler.isEmpty(object)) {
            SystemError.wrapBs("400", "红包不存在或已过期");
        }
        RedRecordCash redRecord = redPacketService.getRedRecordCashById(Long.parseLong(grad.getSerialNumber()));
        UserMerchant inUser = null;
        if(redRecord.payChannel<3){
            if (Boolean.parseBoolean(Config.pp.get("trading.disable.ys"))) {
                SystemError.wrapBs("500", "领取银行卡红包已关闭");
            }
            //查询收红包人钱包信息 uid
            inUser = yinShengService.userMerchant(uid + "");
            if(StringHandler.isEmpty(inUser)){
                SystemError.wrapBs("601", "该用户还未进行银行卡实名认证");
            }
        }
        if(redRecord.payChannel==5){
            if(Logger.isOnline()) {
                if (Boolean.parseBoolean(Config.pp.get("trading.disable.hjzf"))) {
                    SystemError.wrapBs("500", "银行卡转账已关闭");
                }
            }
        }
        //验证用户是否能抢红包
        if (redRecord.getType() != StringHandler.getInt(PayEnum.RedPackageType.Single.getCode())) {
            //群聊
            BaseGroupInfoPO baseGroupInfoPO = GroupUtils.getCacheGroupInfo(redRecord.getGroupName());
            if (baseGroupInfoPO.getIsFreeze()) {
                SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "当前群已被禁止使用");
            }
            String key = GroupKey.groupMembersKey(redRecord.getGroupName());
            Set<String> members = Redis.zSet.range(key, 0, -1);
            if (members == null || members.isEmpty()) {
                SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "当前群已解散");
            } else {
                if (!members.contains(String.valueOf(uid))) {
                    SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "您已不再该群");
                }
            }

            String key2 = GroupKey.bannedRedPacket(redRecord.getGroupName());
            if (Redis.key.exists(key2)) {
                Object o = Redis.hash.hGet(key2, String.valueOf(uid));
                if (StringHandler.isNotEmpty(o)) {
                    SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "该用户已被限制，请联系管理员");
                }
            }
        } else {
            //私聊
            int count = userFriendsMapper.isFriend(uid, String.valueOf(redRecord.getUserId()));
            if (count != 2) {
                SystemError.wrapBs("500", "开启了朋友验证，你还不是他(她)朋友，请先发送朋友验证请求，对方验证通过后，才能聊天。");
            }
            if (FriendsManager.isBlackFriend(StringHandler.getString(redRecord.getUserId()), uid) == 1) {
                SystemError.wrapBs(EnumType.ResponseCode.Fail.getCode(), "你已被对方拉黑");
            }
        }

        String redType = String.valueOf(redRecord.getType());// 红包类型
        returnResult = isGetRedPackage(grad.getSerialNumber(), String.valueOf(uid), redType, StringHandler.getString(uid),redRecord.getGroupName());
        if (!returnResult.success()) {
            SystemError.wrapBs("400", returnResult.getMessage());
        }
        returnResult = redPacketService.getRedPackage(grad.getSerialNumber(), redRecord, StringHandler.getString(uid),inUser,redRecord.payChannel);//自己抢自己的红包不推送
        if (returnResult.success()) {
            //判断是否有规定时间  只能抢多少个红包的判断
            if (StringHandler.isNotEmpty(grad.getGroupId()) && StringHandler.isNotEmpty(grad.getRiskNum()) && grad.getRiskNum() > 0 && StringHandler.isNotEmpty(grad.getRiskTime()) && grad.getRiskTime() > 0) {
                String riskKey = WalletKey.gradUserNumKey(grad.getGroupId(), uid,grad.getRiskTime());
                Redis.str.incr(riskKey);
                if (StringHandler.getInt(Redis.str.get(riskKey)) == 1) {
                    Redis.key.setKeyTimeout(riskKey, StringHandler.getLong(grad.getRiskTime()));
                }
            }
            ThreadUtil.execAsync(() -> {
                LoginInfo cacheUser = UserUtils.getCacheUser(redRecord.getUserId());
                LoginInfo cacheUser2 = UserUtils.getCacheUser(uid);
                String toId = McodeHandler.to32Radix(uid);
                MessageResponseBean messageResponseBean = PayManager.getMessageResponseBean(
                        IdUtil.randomUUID().toUpperCase(), toId, BaseConstants.SINGLE_PREFIX + toId, cacheUser2.getAvatarUrl(), cacheUser.getNickName(),
                        JsonUtil.toJson(MapHandler.initMap("status", "领取完成"
                                , "messageId", redRecord.getMessageId()
                                , "serialNumber", StringHandler.getString(redRecord.getId())
                                , "receiveId", McodeHandler.to32Radix(StringHandler.getLong(redRecord.getListUserId()))
                                , "receiveIds", StringHandler.isNotEmpty(redRecord.getListUserId()) ? McodeHandler.to32Radix(StringHandler.getLong(redRecord.getListUserId())) : ""
                                , "remark", redRecord.getUserId() != uid ? String.format("%s领取了你的红包", cacheUser2.getNickName()) : "你 领取了自己的红包")),
                        DateUtil.getDate(new Date(), BaseConstants.BASE_FORMAT),
                        EnumType.MessageCode.MESSAGE_RED_PACK_GRAD.getCode(), 0.0, 0.0, null,redRecord.payChannel
                );
                messageResponseBean.setAvatarUrl(cacheUser.getAvatarUrl());
                messageResponseBean.setUserName(cacheUser.getNickName());
                if (redRecord.getType() == 1) {
                    GroupUtils.sendIfAbsent(messageResponseBean, String.valueOf(redRecord.getUserId()), BaseConstants.SINGLE_PREFIX + toId);
                } else {
                    messageResponseBean.setFrom(McodeHandler.to32Radix(uid));
                    messageResponseBean.setGroupId(redRecord.getGroupName());
                    messageResponseBean.setGroupPic(GroupUtils.getCacheGroupInfo(redRecord.getGroupName()).getPic());
                    messageResponseBean.setGroupName(UserUtils.getGroupCacheNameByGroupId(redRecord.getGroupName()));
                    GroupUtils.sendIfAbsent(messageResponseBean, String.valueOf(redRecord.getUserId()), BaseConstants.GROUP_PREFIX + redRecord.getGroupName());
                }
            });
        }
        return returnResult.success() ? ResponseHandler.success() : ResponseHandler.error("400", returnResult.getMessage());
    }

    private Result<Map<String, String>> isGetRedPackage(String redId, String uid, String redType, String userId,String groupId) {
        if (redType.equals(PayEnum.RedPackageType.Single.getCode())) {
            String key = RedisKeyToYs.REDIS_RED_SINGLE_PREFIX + redId + "-" + uid;
            if (!Redis.key.exists(key)) {
                return Result.newFailure(-1, "红包已领完");
            }
        } else if (redType.equals(PayEnum.RedPackageType.GroupLuck.getCode())) {
            // 红包缓存
            String key = RedisKeyToYs.REDIS_RED_GROUPLUCK_PREFIX + redId;
            if (!Redis.key.exists(key)) {
                return Result.newFailure(-1, "红包已领完");
            }
            // 已抢红包用户缓存
            String redUserKey = RedisKeyToYs.REDIS_RED_USER_GROUPLUCK_PREFIX + redId;
            List<String> userList = Redis.list.range(redUserKey, 0L, -1L);
            if (StringHandler.isNotEmpty(userList) && userList.contains(userId)) {
                return Result.newFailure(-1, "用户红包已领");
            }
        } else if (redType.equals(PayEnum.RedPackageType.GroupNormal.getCode())) {
            // 红包缓存
            String key = RedisKeyToYs.REDIS_RED_GROUPNORMAL_PREFIX + redId;
            if (!Redis.key.exists(key)) {
                return Result.newFailure(-1, "红包已领完");
            }
            // 已抢红包用户缓存
            String redUserKey = RedisKeyToYs.REDIS_RED_USER_GROUPNORMAL_PREFIX + redId;
            List<String> userList = Redis.list.range(redUserKey, 0L, -1L);
            if (StringHandler.isNotEmpty(userList) && userList.contains(userId)) {
                return Result.newFailure(-1, "用户红包已领");
            }
        } else if (redType.equals(PayEnum.RedPackageType.GroupPersonal.getCode())) {
            // 分配红包用户缓存
            String redUserDisKey = RedisKeyToYs.REDIS_RED_USER_GROUPPERSONAL_DISTRIBUTE_PREFIX + redId;
            List<String> userList = Redis.list.range(redUserDisKey, 0L, -1L);
            if (StringHandler.isEmpty(userList)) {
                return Result.newFailure(-1, "红包已领完");
            }
            if (!userList.contains(uid) && !GroupUtils.isManager(StringHandler.getLong(uid),groupId)) {
                return Result.newFailure(-4, "用户不能领取专属红包");
            }
            // 已抢红包用户缓存
            String redUserKey = RedisKeyToYs.REDIS_RED_USER_GROUPPERSONAL_PREFIX + redId;
            List<String> _userList = Redis.list.range(redUserKey, 0L, -1L);
            if (_userList.contains(userId)) {
                return Result.newFailure(-1, "用户红包已领");
            }
        } else {
            return Result.newFailure(-1, "红包类型错误");
        }
        return Result.newSuccess();
    }

    /**
     * 红包领取记录
     *
     * @param uid
     * @param grad
     * @return
     */
    @RequestMapping("redRecords")
    public String redRecords(@RequestAttribute String uid, RedPacketGrad grad) {
        Map<String, Object> data = redPacketService.redRecords(grad.getSerialNumber(), uid);
        return ResponseHandler.success(data);
    }

    /**
     * 超过10分钟未领取红包
     *
     * @param uid
     * @param groupId
     * @return
     */
    @RequestMapping("unGrad")
    public String unGrad(@RequestAttribute long uid, int groupId,@RequestParam(defaultValue = "3") int payChannel) {
//        if (Boolean.parseBoolean(Config.pp.get("trading.disable"))) {
//            return ResponseHandler.error("500", "交易系统已关闭");
//        }
        Map<String, Object> query = new HashMap<>();
        query.put("uid", StringHandler.getString(uid));
        query.put("groupId", StringHandler.getString(groupId));
        query.put("payChannel", payChannel);
        List<RedRecordCash> packetList = redPacketService.getUnGrad(query);
        if (StringHandler.isEmpty(packetList)) {
            return ResponseHandler.list(new ArrayList<>());
        }
        List<Long> reIds = redPacketService.getGradByRedIds(uid, packetList.stream().map(RedRecordCash::getId).collect(Collectors.toList()));
        List<Map<String, String>> mapList = null;
        if(StringHandler.isNotEmpty(reIds)) {
            mapList = packetList.stream().filter(x -> !reIds.contains(x.getId())).map(redPacket -> {
                LoginInfo cacheUser = UserUtils.getCacheUser(redPacket.getUserId());
                return MapHandler.initMap("serialNumber", StringHandler.getString(redPacket.getId())
                        , "remark", redPacket.getContent()
                        , "amount", StringHandler.fenToYuan(StringHandler.getString(redPacket.getAmount()))
                        , "avatarUrl", cacheUser.getAvatarUrl(), "nickName", cacheUser.getNickName()
                        , "createTime", DateUtil.getDate(redPacket.getRawAddTime(), "yyyy-MM-dd HH:mm:ss")
                        , "payChannel", StringHandler.getString(redPacket.payChannel)
                );
            }).collect(Collectors.toList());
        }else{
            mapList = packetList.stream().map(redPacket -> {
                LoginInfo cacheUser = UserUtils.getCacheUser(redPacket.getUserId());
                return MapHandler.initMap("serialNumber", StringHandler.getString(redPacket.getId())
                        , "remark", redPacket.getContent()
                        , "amount", StringHandler.fenToYuan(StringHandler.getString(redPacket.getAmount()))
                        , "avatarUrl", cacheUser.getAvatarUrl(), "nickName", cacheUser.getNickName()
                        , "createTime", DateUtil.getDate(redPacket.getRawAddTime(), "yyyy-MM-dd HH:mm:ss")
                        , "payChannel", StringHandler.getString(redPacket.payChannel)
                );
            }).collect(Collectors.toList());
        }
        return ResponseHandler.list(mapList);
    }

    @RequestMapping("redOrders")
    public String redOrders() {
        Map<String, Object> data = new HashMap<>();
        data.put("swith", false);
        data.put("remark", "我是开关");
        data.put("orders", "0,1,2".split(","));
        return ResponseHandler.success();
    }

    /**
     * 红包明细接口
     * @param uid
     * @param redType   2我收到的红包   1我发出胡的红包
     * @param dataBegin 当前页数据开始值
     * @param dataSize  每页数据条数
     * @return
     */
    @RequestMapping("list")
    public String list(@RequestAttribute Long uid,@RequestParam(defaultValue = "2")int redType,@RequestParam(defaultValue = "0")int dataBegin,@RequestParam(defaultValue = "20")int dataSize){
        Map<String,Object> param = new HashMap<>();
        param.put("uid",uid);
        param.put("redType",redType);
        param.put("dataBegin",dataBegin);
        param.put("dataSize",dataSize);
        String dayTime = DateHandler.getDate(DateHandler.getDate(StringHandler.getInt(Config.pp.get("ys.del.data.select.day.number"),-4)))+" 00:00:00";
        param.put("dayTime",dayTime);
        List<Map<String,Object>> list = redPacketService.getRedListByUser(param);
        return ResponseHandler.list(list.stream().peek(x->{
            if(redType==1){
                x.put("type",PayEnum.RedPackageType.getObjectByCode(StringHandler.getString(x.get("type"))).getName());
            }
            x.put("amount",StringHandler.fenToYuan(StringHandler.getString(x.get("amount"))));
            x.put("addTime",StringHandler.getString(x.get("addTime")).replace(".0",""));
            x.put("alias",McodeHandler.to32Radix(StringHandler.getLong(x.get("uid"))));
        }).collect(Collectors.toList()));
    }
}
